package org.soar.views.uicomponent;

import java.lang.reflect.Field;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewManager;

import com.google.inject.Inject;
import org.soar.views.annotation.ViewById;

public abstract class SoarUIComponent {

	protected LayoutInflater inflater = null;
	protected ViewGroup parent = null;
	protected Context context = null;
	protected Map data = null;
	protected View view = null;	
	protected UIComponentConfig uiConfig = null;
	
	public static final int COMPONENT = 0x7f05aaaa;
	@Inject
	private TransitionManager transitionManager;
	@Inject
	private SoarUIFinder soarUIFinder;
	
	// no need to build things, no need to push history, cause it must be from history
	public void initFromCache(Context context,ViewGroup parent, Map data,UIComponentConfig config) {
		initBaseMembers(context, parent, data, config);
		renderUIComponnent();
		this.onStart();
	}
	
	public void init(Context context,ViewGroup parent, Map data,UIComponentConfig config) {
		initBaseMembers(context, parent, data, config);
		
		this.view = this.build();
		renderUIComponnent();
		renderMembersWithAnnotation();
		
		view.setTag(COMPONENT, this);
		this.afterBuild();
		this.onStart();
	}
	
	private void initBaseMembers(Context context,ViewGroup parent, Map data,UIComponentConfig config){
		uiConfig = this.buildConfigs();
		uiConfig.extend(config);
		if(parent == null){
			parent = (ViewGroup) ((Activity)context).findViewById(uiConfig.getParentId());
		}
		this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		this.context = context;
		this.data = data;
		this.parent = parent;
		
	}
	
	private void renderMembersWithAnnotation(){
		Class cls = this.getClass();

        while (cls != SoarUIComponent.class) {
        	
        	Field[] fields = cls.getDeclaredFields();
    		for(int i = 0; i < fields.length; i++){
    			Field field = fields[i];
    			ViewById anno =  field.getAnnotation(ViewById.class);
    			if ( anno != null){
    				try {
    					int id = anno.id();
    					//TODO: make id default with the field name
    					field.setAccessible(true);
    					field.set(this, this.view.findViewById(id));
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		}
        	
            cls = cls.getSuperclass();
        }
		
	}
	
	protected UIComponentConfig buildConfigs() {
		UIComponentConfig uiConfig = new UIComponentConfig();
		return uiConfig;
	}

	private void renderUIComponnent(){
		//TODO: avoid dupcliate append
		if (view.getParent() != null && view.getParent().equals(parent)) {
			parent.removeView(view);
		}
		
		if(uiConfig.getTransition() != null && !uiConfig.getTransition().equals("")){
			TransitionFunction function = transitionManager.getTransition(uiConfig.getTransition());
			function.doTransition(this,data,uiConfig,parent);
		}else{
			if(uiConfig.isEmptyParent()){
				soarUIFinder.empty(this.parent);
			}
			this.parent.addView(view);
		}
	}
	
	

	protected abstract View build();
	protected void afterBuild(){}
	
	public void destory(){
		synchronized(this){
			this.onDestory();
			//TODO: avoid duplicate delete
			if(view.getParent() != null){
				((ViewManager)view.getParent()).removeView(view);
			}
			
			if(!uiConfig.isCache()){
				this.view = null;
				this.data = null;
				this.uiConfig = null;
			}
		}
	}
	
	protected void onDestory() {}
	protected void onStart() {}

	public ViewGroup getParent() {
		return parent;
	}
	public Map getData() {
		return data;
	}

	public void setData(Map data) {
		this.data = data;
	}

	public UIComponentConfig getUiConfig() {
		return uiConfig;
	}

	public void setUiConfig(UIComponentConfig uiConfig) {
		this.uiConfig = uiConfig;
	}

	public Context getContext() {
		return context;
	}

	public View getView() {
		return view;
	}

}